/*
 * Copyright (c) 2007 IJO Technologies Ltd.
 * www.ijotechnologies.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * IJO Technologies ("Confidential Information").
 * You shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement you
 * entered into with IJO Technologies.
 */

package com.igola.appconfig;

import org.springframework.core.io.ClassPathResource;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;

/**
 * @author Daiyu Chen
 */
public class AppConfigParameters implements Serializable {
    static final String SALT = "#igola@appconfig2016!#";
    static final String NOT_FOUND_ERROR_TEMPLATE = "Not found properties file [%s]";
    static final String VERIFY_FAILED = "Verify is failed";
    static final String FILE_NAME_TEMPLATE = "%s.properties";
    static final String VERSION_FORMAT_INVALID_TEMPLATE = "[%s] version [%s] format invalid";
    static final String BUILD_VERSION_INVALID_TEMPLATE = "[%s] build version [%s] format invalid";
    String os;
    String version;
    String sign;

    // DEV,SIT,UAT,PROD
    String environment;

    public AppConfigParameters() {
    }

    public void setOs(String os) {
        this.os = os;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public void setEnvironment(String environment) {
        this.environment = environment;
    }

    public boolean verify() {
        return sign.equals(md5());
    }

    public Map properties() {
        if (verify()) {
            try {
                ClassPathResource classPathResource = new ClassPathResource(String.format(FILE_NAME_TEMPLATE, filename()));
                File propertyFile = classPathResource.getFile();
                File absoluteFile = propertyFile.getAbsoluteFile();
                FileReader fileReader = new FileReader(absoluteFile);
                Properties properties = new Properties();
                properties.load(fileReader);
                if (forIos()) {
                    properties.setProperty("production", production().toString());
                }
                fileReader.close();
                return new HashMap<>(properties);
            } catch (IOException e) {
                throw new UnsupportedOperationException(String.format(NOT_FOUND_ERROR_TEMPLATE, String.format(FILE_NAME_TEMPLATE, filename())));
            }
        }
        throw new UnsupportedOperationException(VERIFY_FAILED);
    }

    private String md5() {
        String willMD5 = filename() + SALT;
        return DigestUtils.md5DigestAsHex(willMD5.getBytes()).toUpperCase();
    }

    private boolean forIos() {
        return os.equalsIgnoreCase("ios");
    }

    private String filename() {
        if (forIos()) {
            return os.toLowerCase() + version;
        }
        String env = "dev";
        if (!StringUtils.isEmpty(environment)) {
            env = environment.toLowerCase();
        }
        return String.format("%s.%s%s", env, os.toLowerCase(), version);
    }

    private Boolean production() {
        String[] versions = version.split("-");
        if (StringUtils.isEmpty(versions) || versions.length == 1) {
            throw new UnsupportedOperationException(String.format(VERSION_FORMAT_INVALID_TEMPLATE, os, version));
        }
        String buildVersion = versions[versions.length - 1];
        String[] buildVersionNum = buildVersion.split("\\.");
        if (buildVersionNum.length == 2) {
            return true;
        }
        if (buildVersionNum.length == 3) {
            return false;
        }
        throw new UnsupportedOperationException(String.format(BUILD_VERSION_INVALID_TEMPLATE, os, buildVersion));
    }
}
